#!/usr/bin/env python3
"""
安全日志分析工具
用于分析和监控API安全事件
"""

import redis
import json
from datetime import datetime, timedelta
from collections import defaultdict, Counter
import argparse
from config import Config

class SecurityLogAnalyzer:
    """安全日志分析器"""
    
    def __init__(self, redis_url=None):
        """初始化安全日志分析器"""
        if redis_url is None:
            redis_url = Config.REDIS_URL
            
        try:
            self.redis_client = redis.from_url(redis_url, decode_responses=True)
            # 测试连接
            self.redis_client.ping()
            print(f"✅ Redis连接成功: {redis_url}")
        except redis.ConnectionError as e:
            print(f"⚠️ Redis连接失败: {str(e)}")
            print("使用模拟数据进行演示")
            self.redis_client = None
    
    def get_security_logs(self, hours=24):
        """获取指定时间范围内的安全日志"""
        if not self.redis_client:
            # 返回模拟数据用于演示
            return self._get_mock_security_logs()
            
        logs = []
        cutoff_time = datetime.now() - timedelta(hours=hours)
        
        try:
            for key in self.redis_client.scan_iter(match="security_log:*"):
                log_data = self.redis_client.get(key)
                if log_data:
                    try:
                        log = json.loads(log_data)
                        log_time = datetime.fromisoformat(log['timestamp'])
                        if log_time >= cutoff_time:
                            logs.append(log)
                    except (json.JSONDecodeError, KeyError, ValueError):
                        continue
        except redis.ConnectionError:
            print("⚠️ Redis连接中断，返回空日志")
            return []
            
        return sorted(logs, key=lambda x: x['timestamp'], reverse=True)
    
    def _get_mock_security_logs(self):
        """生成模拟安全日志数据用于演示"""
        mock_logs = [
            {
                'timestamp': (datetime.now() - timedelta(hours=1)).isoformat(),
                'event_type': 'rate_limit_exceeded',
                'client_ip': '192.168.1.100',
                'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                'details': {'endpoint': '/api/users', 'limit': 100}
            },
            {
                'timestamp': (datetime.now() - timedelta(hours=2)).isoformat(),
                'event_type': 'invalid_input',
                'client_ip': '10.0.0.50',
                'user_agent': 'curl/7.68.0',
                'details': {'validation_error': 'SQL注入尝试', 'data_sample': "'; DROP TABLE users; --"}
            },
            {
                'timestamp': (datetime.now() - timedelta(hours=3)).isoformat(),
                'event_type': 'rate_limit_exceeded',
                'client_ip': '172.16.0.25',
                'user_agent': 'python-requests/2.25.1',
                'details': {'endpoint': '/api/login', 'limit': 10}
            }
        ]
        return mock_logs
    
    def analyze_rate_limit_events(self, logs):
        """分析频率限制事件"""
        rate_limit_logs = [log for log in logs if log.get('event_type') == 'rate_limit_exceeded']
        
        if not rate_limit_logs:
            print("📊 频率限制分析: 无相关事件")
            return
        
        print(f"📊 频率限制分析 (共 {len(rate_limit_logs)} 个事件)")
        print("-" * 50)
        
        # 按IP统计
        ip_counter = Counter(log.get('client_ip') for log in rate_limit_logs)
        print("🌐 按IP统计:")
        for ip, count in ip_counter.most_common(10):
            print(f"  {ip}: {count} 次")
        
        # 按端点统计
        endpoint_counter = Counter(log.get('details', {}).get('endpoint') for log in rate_limit_logs)
        print("\n🎯 按端点统计:")
        for endpoint, count in endpoint_counter.most_common():
            print(f"  {endpoint}: {count} 次")
        
        # 按时间分布
        hour_counter = defaultdict(int)
        for log in rate_limit_logs:
            try:
                timestamp = datetime.fromisoformat(log.get('timestamp', '').replace('Z', '+00:00'))
                hour = timestamp.hour
                hour_counter[hour] += 1
            except:
                pass
        
        print("\n⏰ 按小时分布:")
        for hour in sorted(hour_counter.keys()):
            print(f"  {hour:02d}:00 - {hour_counter[hour]} 次")
    
    def analyze_invalid_input_events(self, logs):
        """分析无效输入事件"""
        invalid_input_logs = [log for log in logs if log.get('event_type') == 'invalid_input']
        
        if not invalid_input_logs:
            print("\n🛡️ 输入验证分析: 无相关事件")
            return
        
        print(f"\n🛡️ 输入验证分析 (共 {len(invalid_input_logs)} 个事件)")
        print("-" * 50)
        
        # 按IP统计
        ip_counter = Counter(log.get('client_ip') for log in invalid_input_logs)
        print("🌐 按IP统计:")
        for ip, count in ip_counter.most_common(10):
            print(f"  {ip}: {count} 次")
        
        # 按验证错误类型统计
        error_counter = Counter(log.get('details', {}).get('validation_error') for log in invalid_input_logs)
        print("\n⚠️ 按错误类型统计:")
        for error, count in error_counter.most_common():
            print(f"  {error}: {count} 次")
        
        # 显示最近的攻击样本
        print("\n🔍 最近的攻击样本:")
        for log in invalid_input_logs[-5:]:
            timestamp = log.get('timestamp', '')
            error = log.get('details', {}).get('validation_error', '')
            sample = log.get('details', {}).get('data_sample', '')[:100]
            print(f"  {timestamp}: {error}")
            print(f"    样本: {sample}...")
    
    def analyze_user_agents(self, logs):
        """分析用户代理"""
        user_agents = [log.get('user_agent', '') for log in logs if log.get('user_agent')]
        
        if not user_agents:
            print("\n🤖 用户代理分析: 无数据")
            return
        
        print(f"\n🤖 用户代理分析 (共 {len(user_agents)} 个记录)")
        print("-" * 50)
        
        # 统计用户代理
        ua_counter = Counter(user_agents)
        
        print("📱 常见用户代理:")
        for ua, count in ua_counter.most_common(10):
            ua_short = ua[:80] + "..." if len(ua) > 80 else ua
            print(f"  {count:3d}x {ua_short}")
        
        # 检测可疑用户代理
        suspicious_patterns = ['bot', 'crawler', 'spider', 'scan', 'curl', 'wget', 'python']
        suspicious_uas = []
        
        for ua in set(user_agents):
            ua_lower = ua.lower()
            for pattern in suspicious_patterns:
                if pattern in ua_lower:
                    suspicious_uas.append(ua)
                    break
        
        if suspicious_uas:
            print("\n🚨 可疑用户代理:")
            for ua in suspicious_uas[:10]:
                count = ua_counter[ua]
                ua_short = ua[:80] + "..." if len(ua) > 80 else ua
                print(f"  {count:3d}x {ua_short}")
    
    def generate_security_report(self, hours=24):
        """生成安全报告"""
        print("🔐 API安全分析报告")
        print("=" * 60)
        print(f"📅 时间范围: 最近 {hours} 小时")
        print(f"🕐 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 60)
        
        # 获取日志
        try:
            logs = self.get_security_logs(hours)
        except Exception as e:
            print(f"❌ 获取日志失败: {str(e)}")
            return
        
        if not logs:
            print("📝 无安全日志数据")
            return
        
        print(f"📝 总日志条数: {len(logs)}")
        
        # 事件类型统计
        event_types = Counter(log.get('event_type') for log in logs)
        print("\n📊 事件类型统计:")
        for event_type, count in event_types.most_common():
            print(f"  {event_type}: {count} 次")
        
        # 分析各类事件
        self.analyze_rate_limit_events(logs)
        self.analyze_invalid_input_events(logs)
        self.analyze_user_agents(logs)
        
        # 总体安全状况评估
        print("\n🎯 安全状况评估")
        print("-" * 50)
        
        total_events = len(logs)
        rate_limit_events = len([log for log in logs if log.get('event_type') == 'rate_limit_exceeded'])
        invalid_input_events = len([log for log in logs if log.get('event_type') == 'invalid_input'])
        
        if total_events == 0:
            print("✅ 系统安全状况良好，无异常事件")
        else:
            print(f"⚠️ 检测到 {total_events} 个安全事件")
            
            if rate_limit_events > 0:
                print(f"  - 频率限制触发: {rate_limit_events} 次")
            
            if invalid_input_events > 0:
                print(f"  - 恶意输入拦截: {invalid_input_events} 次")
            
            # 安全建议
            print("\n💡 安全建议:")
            
            if rate_limit_events > 100:
                print("  - 考虑调整频率限制策略")
                print("  - 监控高频请求的IP地址")
            
            if invalid_input_events > 50:
                print("  - 加强输入验证规则")
                print("  - 考虑添加IP黑名单功能")
            
            if total_events > 500:
                print("  - 建议启用更严格的安全策略")
                print("  - 考虑添加验证码机制")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='安全日志分析器')
    parser.add_argument('--hours', type=int, default=24, help='分析最近N小时的日志 (默认: 24)')
    parser.add_argument('--redis-url', type=str, default=None, help=f'Redis连接URL (默认: {Config.REDIS_URL})')
    
    args = parser.parse_args()
    
    # 创建分析器实例
    analyzer = SecurityLogAnalyzer(args.redis_url)
    
    # 生成安全报告
    analyzer.generate_security_report(args.hours)

if __name__ == '__main__':
    main()